package digitRecognitionProblem.learnWeights;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import mlp.Mlp;
import mlp.MlpExamples;
import digitRecognitionProblem.DigitRecognitionMlpFitness;
 
/**
 * Retrains the neural networks resulting from LW_main, that is, uses the optimal
 * initial weights that were found in order to train the network better.
 * The resulting network is tested on validate 1
 * ATTENTION: before running, the activation function of mlp.Neuron.java must be set to ReLu
 */
public class Retrain {

	private enum ArgNums {
		DIGIT, MLP_DIRECTORY
	}
	
	public static void main(String[] args) {
		
		// read input arguments		
		int digit = Integer.parseInt(args[ArgNums.DIGIT.ordinal()]); // which digit should recognize
		String mlpDir = args[ArgNums.MLP_DIRECTORY.ordinal()]; // directory with serialized neural networks
		
		// read mlp
		FileInputStream readFile;
		Mlp mlp = null;
		try {
//			readFile = new FileInputStream("mlp_best_start_rec_" + digit + ".txt");
//			readFile = new FileInputStream("/home/ofri/Desktop/MLPs/28_4_new_func_starts/"+digit+"/mlp_0_rec_"+digit+".txt");
//			readFile = new FileInputStream("/home/ofri/Desktop/MLPs/testClassifier/"+ digit + "/28_4_best_start_mlp_0_rec_" + digit + ".txt");
			readFile = new FileInputStream(mlpDir + "/mlp_0_rec_" + digit + ".txt");

			ObjectInputStream fileStream = new ObjectInputStream(readFile);
			mlp = (Mlp)fileStream.readObject();
			fileStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		// train network
		float[] initWeights = {0.0625f, 0.0625f, 0.078125f, 0.03125f, 0.09375f,  0.03125f, 0.125f, 0.09375f, 0.0625f, 0.140625f};
		Mlp.INIT_WEIGHT_RANGE = initWeights[digit];
		Mlp.ERROR_RATE = 0.005f;

		MlpExamples trainExamples = new MlpExamples("train_reduce.csv", 0, 38000, digit);		
		mlp.learn(trainExamples.getInput(), trainExamples.getOutput(), 30);
		
		// test network
		DigitRecognitionMlpFitness.initTestData("validate1_reduce.csv", digit);
		DigitRecognitionMlpFitness funcFit = new DigitRecognitionMlpFitness(mlp);		
		System.out.println("Success rate on test set: "+ funcFit.getFitness(null));

		FileOutputStream writeFile;
		try {
			writeFile = new FileOutputStream("REFINED_mlp_0_rec_" + digit + ".txt");
			ObjectOutputStream fileStream = new ObjectOutputStream(writeFile);
			fileStream.writeObject(mlp);
			fileStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
